//! JavaScript 渲染引擎 - 基于 headless_chrome

#[cfg(feature = "js-rendering")]
use headless_chrome::{Browser, LaunchOptionsBuilder, Tab};
#[cfg(feature = "js-rendering")]
use std::sync::Arc;
#[cfg(feature = "js-rendering")]
use std::time::Duration;
#[cfg(feature = "js-rendering")]
use anyhow::Result;
#[cfg(feature = "js-rendering")]
use log::{debug, error, info};

/// JavaScript 渲染器配置
#[derive(Debug, Clone)]
pub struct JsRendererConfig {
    /// 页面加载超时（秒）
    pub timeout_secs: u64,
    /// 等待 JavaScript 执行时间（毫秒）
    pub wait_for_js_ms: u64,
    /// 是否启用无头模式
    pub headless: bool,
    /// 视口宽度
    pub viewport_width: u32,
    /// 视口高度
    pub viewport_height: u32,
    /// 是否禁用图片加载
    pub disable_images: bool,
}

impl Default for JsRendererConfig {
    fn default() -> Self {
        Self {
            timeout_secs: 30,
            wait_for_js_ms: 2000,
            headless: true,
            viewport_width: 1920,
            viewport_height: 1080,
            disable_images: true,
        }
    }
}

/// JavaScript 渲染引擎
#[cfg(feature = "js-rendering")]
pub struct JsRenderer {
    browser: Arc<Browser>,
    config: JsRendererConfig,
}

#[cfg(feature = "js-rendering")]
impl JsRenderer {
    /// 创建新的 JS 渲染器
    pub fn new(config: JsRendererConfig) -> Result<Self> {
        info!("Initializing JavaScript renderer with headless_chrome...");

        let launch_options = LaunchOptionsBuilder::default()
            .headless(config.headless)
            .idle_browser_timeout(Duration::from_secs(config.timeout_secs))
            .build()?;

        let browser = Browser::new(launch_options)?;

        info!("JavaScript renderer initialized successfully");

        Ok(Self {
            browser: Arc::new(browser),
            config,
        })
    }

    /// 渲染页面并返回内容
    pub async fn render(&self, url: &str) -> Result<RenderedPage> {
        debug!("Rendering page with JavaScript: {}", url);

        let tab = self.browser.new_tab()?;

        // 设置视口大小
        tab.set_bounds(headless_chrome::types::Bounds::Normal {
            left: Some(0),
            top: Some(0),
            width: Some(self.config.viewport_width),
            height: Some(self.config.viewport_height),
        })?;

        // 导航到URL
        tab.navigate_to(url)?;

        // 等待页面加载
        tab.wait_until_navigated()?;

        // 等待 JavaScript 执行
        tokio::time::sleep(Duration::from_millis(self.config.wait_for_js_ms)).await;

        // 获取最终的 HTML 内容
        let html = tab.get_content()?;

        // 获取页面标题
        let title = tab.get_title();

        // 获取所有 cookies
        let cookies = tab.get_cookies()?;

        // 获取页面中的所有链接
        let links = self.extract_links(&tab)?;

        // 获取响应状态码（通过 evaluate）
        let status_code = self.get_response_status(&tab).unwrap_or(200);

        // 关闭 tab
        tab.close(true)?;

        debug!("Successfully rendered page: {} (status: {})", url, status_code);

        Ok(RenderedPage {
            url: url.to_string(),
            html,
            title,
            status_code,
            cookies: cookies.iter().map(|c| (c.name.clone(), c.value.clone())).collect(),
            links,
        })
    }

    /// 提取页面中的所有链接
    fn extract_links(&self, tab: &Arc<Tab>) -> Result<Vec<String>> {
        let script = r#"
            Array.from(document.querySelectorAll('a[href]'))
                .map(a => a.href)
                .filter(href => href && href.startsWith('http'));
        "#;

        let result = tab.evaluate(script, false)?;

        if let Some(value) = result.value {
            if let Ok(links) = serde_json::from_value::<Vec<String>>(value) {
                return Ok(links);
            }
        }

        Ok(vec![])
    }

    /// 获取响应状态码
    fn get_response_status(&self, tab: &Arc<Tab>) -> Result<u16> {
        let script = "window.performance.getEntriesByType('navigation')[0]?.responseStatus || 200";

        let result = tab.evaluate(script, false)?;

        if let Some(value) = result.value {
            if let Ok(status) = serde_json::from_value::<u16>(value) {
                return Ok(status);
            }
        }

        Ok(200)
    }
}

#[cfg(feature = "js-rendering")]
impl Drop for JsRenderer {
    fn drop(&mut self) {
        // Browser 会自动清理
        debug!("Dropping JavaScript renderer");
    }
}

/// 渲染后的页面数据
#[derive(Debug, Clone)]
pub struct RenderedPage {
    /// URL
    pub url: String,
    /// 渲染后的 HTML
    pub html: String,
    /// 页面标题
    pub title: String,
    /// HTTP 状态码
    pub status_code: u16,
    /// Cookies
    pub cookies: Vec<(String, String)>,
    /// 页面中的链接
    pub links: Vec<String>,
}

// Stub 实现（当 js-rendering feature 未启用时）
#[cfg(not(feature = "js-rendering"))]
pub struct JsRenderer;

#[cfg(not(feature = "js-rendering"))]
impl JsRenderer {
    pub fn new(_config: JsRendererConfig) -> Result<Self, anyhow::Error> {
        Err(anyhow::anyhow!("JavaScript rendering is not enabled. Please compile with --features js-rendering"))
    }
}

#[cfg(not(feature = "js-rendering"))]
#[derive(Debug, Clone)]
pub struct RenderedPage {
    pub url: String,
    pub html: String,
    pub title: String,
    pub status_code: u16,
    pub cookies: Vec<(String, String)>,
    pub links: Vec<String>,
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_renderer_config_default() {
        let config = JsRendererConfig::default();
        assert_eq!(config.timeout_secs, 30);
        assert_eq!(config.headless, true);
        assert_eq!(config.viewport_width, 1920);
    }
}
